/*

  cone search

  Copyright © 2012 F.Hroch (hroch@physics.muni.cz)

  This file is part of Munipack.

  Munipack is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.
  
  Munipack is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License
  along with Munipack.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "xmunipack.h"
#include <wx/wx.h>
#include <wx/animate.h>
#include <wx/statline.h>
#include <wx/regex.h>


// --- MuniCone


MuniCone::MuniCone(wxWindow *w, MuniConfig *c, const std::vector<VOResolv>& v):
  wxDialog(w,wxID_ANY,"Catalogues Search"),config(c),vores(v),
  throbber(new wxAnimationCtrl(this,wxID_ANY,c->throbber)),
  running(false),pipe(this)
{
  SetIcon(config->munipack_icon);

  wxSizerFlags lf, cf, uf, sl;
  lf.Align(wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT);
  cf.Align(wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT);
  uf.Align(wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT);
  sl.Border().Expand();

  wxStaticText *label;

  wxFont bf(*wxNORMAL_FONT);
  bf.SetWeight(wxFONTWEIGHT_BOLD);

  wxFont sf(*wxSMALL_FONT);

  // title
  wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
  wxBoxSizer *st = new wxBoxSizer(wxHORIZONTAL);

  MuniArtIcons ico(wxART_MESSAGE_BOX,wxSize(48,48));
  st->Add(new wxStaticBitmap(this,wxID_ANY,ico.Icon(wxART_FIND)),wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
  wxStaticText *title = new wxStaticText(this,wxID_ANY,"Catalogues Search");
  title->SetFont(bf);
  st->Add(title,wxSizerFlags().DoubleBorder().Center());
  topsizer->Add(st,wxSizerFlags().Border().Center());
  topsizer->Add(new wxStaticLine(this,wxID_ANY),sl);

  // form
  wxFlexGridSizer *grid = new wxFlexGridSizer(2);
  grid->AddGrowableCol(1);
  
  label = new wxStaticText(this,wxID_ANY,"Catalogue:");
  grid->Add(label,lf);
  wxArrayString catalogs;
  for(size_t i = 0; i < vores.size(); i++)
    catalogs.Add(vores[i].name);
  /*
  catalogs.Add("UCAC 3");
  catalogs.Add("GSC 2.3");
  */
  wxChoice *wcat = new wxChoice(this,wxID_ANY,wxDefaultPosition,wxDefaultSize,catalogs);
  wcat->SetSelection(0);
  grid->Add(wcat,cf);

  wxBoxSizer *ss;

  label = new wxStaticText(this,wxID_ANY,"Center in α:");
  grid->Add(label,lf);
  ss = new wxBoxSizer(wxHORIZONTAL);
  walpha = new wxSpinCtrlDouble(this,wxID_ANY,"",wxDefaultPosition,wxDefaultSize,
				wxSP_ARROW_KEYS|wxTE_PROCESS_ENTER,0.0,360.0,0.0,0.01);
  ss->Add(walpha);
  ss->Add(new wxStaticText(this,wxID_ANY,"[°]"),uf);
  grid->Add(ss,cf);

  label = new wxStaticText(this,wxID_ANY,"Center in δ:");
  grid->Add(label,lf);
  ss = new wxBoxSizer(wxHORIZONTAL);
  wdelta = new wxSpinCtrlDouble(this,wxID_ANY,"",wxDefaultPosition,wxDefaultSize,
				wxSP_ARROW_KEYS|wxTE_PROCESS_ENTER,-90.0,90.0,0.0,0.01);
  ss->Add(wdelta);
  ss->Add(new wxStaticText(this,wxID_ANY,"[°]"),uf);
  grid->Add(ss,cf);

  label = new wxStaticText(this,wxID_ANY,"Cone Radius:");
  grid->Add(label,lf);

  wradius = new wxSpinCtrlDouble(this,wxID_ANY,"",wxDefaultPosition,wxDefaultSize,
				 wxSP_ARROW_KEYS|wxTE_PROCESS_ENTER,0.0,100.0,0.1,0.01);
  ss = new wxBoxSizer(wxHORIZONTAL);
  ss->Add(wradius);
  ss->Add(new wxStaticText(this,wxID_ANY,"[°]"),uf);
  grid->Add(ss,cf);


  wxBoxSizer *sb = new wxBoxSizer(wxHORIZONTAL);

  sb->Add(throbber,lf);
  status = new wxStaticText(this,wxID_ANY,"Some description");
  status->SetFont(sf);
  sb->Add(status,wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL).Border());

  wxCollapsiblePane *collPane = new wxCollapsiblePane(this,wxID_ANY,"Options");
  wxWindow *win = collPane->GetPane();

  ss = new wxBoxSizer(wxHORIZONTAL);
  ss->Add(new wxStaticText(win,wxID_ANY,"Save To:"),cf.Border(wxLEFT));
  wxFilePickerCtrl *ls = new wxFilePickerCtrl(win,wxID_ANY,"","Select A File",
					      "FITS files "+config->dirmask+")|"+
					      config->dirmask+"| All files (*)|*",
					      wxDefaultPosition,wxDefaultSize,
					      wxFLP_SAVE|wxFLP_OVERWRITE_PROMPT|wxFLP_USE_TEXTCTRL|wxFLP_SMALL);
  ss->Add(ls,cf.Expand().Proportion(1).Border(wxRIGHT));

  win->SetSizer(ss);
  ss->SetSizeHints(win);


  topsizer->Add(grid,wxSizerFlags().Center());
  topsizer->Add(sb,wxSizerFlags().Center());
  topsizer->Add(collPane,wxSizerFlags().Expand());
  search = new wxButton(this,wxID_FIND,"Search");
  topsizer->Add(search,wxSizerFlags().Border().Expand());

  SetSizer(topsizer);

  Bind(wxEVT_COMMAND_BUTTON_CLICKED,&MuniCone::OnSearch,this,wxID_FIND);
  Bind(wxEVT_COMMAND_FILEPICKER_CHANGED,&MuniCone::OnSave,this,ls->GetId());
  Bind(wxEVT_COMMAND_CHOICE_SELECTED,&MuniCone::OnService,this,wcat->GetId());

  throbber->Show(false);
  status->Show(false);
  Fit();

  //  catalog = "http://www.nofs.navy.mil/cgi-bin/vo_cone.cgi?CAT=UCAC-3&";
  //catalog = "http://vizier.u-strasbg.fr/viz-bin/votable/-A?-source=I/315&";
  catalog = vores[0].service;
  sortcol = vores[0].mag;
}

MuniCone::~MuniCone()
{
  if( ! savename.IsEmpty() )
    wxRemoveFile(coutput);
}

void MuniCone::OnClose(wxCloseEvent& event)
{
  wxLogDebug("MuniCone::OnClose");

  // Arranging of the code is really important
  // A use of Close() doesn't work because the event-system have no break
  // to execute other events (finishing subprocesses).
  if( running ) {
    pipe.Stop();
    wxQueueEvent(this,event.Clone());
  }
  else
    // Skipping here passes processing of Close event to default handler.
    event.Skip();
}

void MuniCone::OnService(wxCommandEvent& event)
{
  catalog = vores[event.GetInt()].service;
  sortcol = vores[event.GetInt()].mag;
  key_alpha = vores[event.GetInt()].ra;
  key_delta = vores[event.GetInt()].dec;

  //  switch(event.GetInt()){
    //  case 0: catalog = "http://www.nofs.navy.mil/cgi-bin/vo_cone.cgi?CAT=UCAC-3&"; break;
  //  case 0: catalog = "http://vizier.u-strasbg.fr/viz-bin/votable/-A?-source=I/315&"; break;
  //  case 1: catalog = "http://vizier.u-strasbg.fr/viz-bin/votable/-A?-source=I/305&"; break;
   //  case 1: catalog = "http://mastclustera.stsci.edu/webservices/vo/ConeSearch.aspx?CAT=GSC23&"; break;
   //  case 2: catalog = "http://vizier.u-strasbg.fr/viz-bin/votable/-A?-source=I/289&"; break;
  //  }
}

void MuniCone::OnSearch(wxCommandEvent& event)
{
  if( running ) {
    pipe.Stop();
    status->SetLabel("Interrupted.");
    return;
  }


  Bind(wxEVT_END_PROCESS,&MuniCone::OnFinish,this);
  
  MuniProcess *cone = new MuniProcess(&pipe,"cone");
  pipe.push(cone);

  coutput = wxFileName::CreateTempFileName("xmunipack-cone-search_");
  wxRemoveFile(coutput);

  //  cone->Write("SORT = 'Va'"); // !!!! just only for UCAC-3 !!!!
  cone->Write("SORT = '"+sortcol+"'");
  cone->Write("TYPE = 'FITS'");
  cone->Write("OUTPUT = '" + coutput + "'");
  cone->Write("URL = '" + catalog + "'");

  wxString a;

  a.Printf("SR = '%lf'",wradius->GetValue());
  cone->Write(a);
  a.Printf("RA = '%lf'",walpha->GetValue());
  cone->Write(a);
  a.Printf("DEC = '%lf'",wdelta->GetValue());
  cone->Write(a);

  throbber->Show(true);
  throbber->Play();
  status->Show(true);
  status->SetLabel("Connecting VO...");
  search->SetLabel("STOP");
  running = true;
  Layout();
  Fit();

  pipe.Start();
}

void MuniCone::OnFinish(wxProcessEvent& event)
{
  wxLogDebug("MuniCone::OnFinish");

  Unbind(wxEVT_END_PROCESS,&MuniCone::OnFinish,this);

  throbber->Stop();
  throbber->Show(false);
  search->SetLabel("Search");
  running = false;
  Layout();
  Fit();

  ParseOutput(pipe.GetOutput());

  if( ! savename.IsEmpty() )
    wxRenameFile(coutput,savename);
}

void MuniCone::OnSave(wxFileDirPickerEvent& event)
{
  savename = event.GetPath();
}

void MuniCone::ParseOutput(const wxArrayString& out)
{
  for(size_t i = 0; i < out.GetCount(); i++) {
    wxString l(out[i]);

    wxRegEx re("=CONE>");
    wxASSERT(re.IsValid());
    if( re.Matches(l) ) {
      size_t i1,i2;
      re.GetMatch(&i1,&i2);
      l = l.Mid(i1+i2);
      status->SetLabel(l);
      
    }
  }
}

